iT邦幫忙

2023 iThome 鐵人賽

DAY 25
1
Modern Web

轉職三年 web 仔:不僅是代碼,更是人生的重構系列 第 25

人生重構 Day25:新功能中實作—產品優化與重構

  • 分享至 

  • xImage
  •  

職場上的每個角色,不是組織的一枚小螺絲,他們是構成整個組織的靈魂

這句話告訴了我們,不論在社會或是其他任何領域,每個人都是一個不可或缺的角色。它不僅凸顯了組織的核心價值,也突出了每位成員在支持組織長期運作和成功方面的關鍵作用。也強調了團隊合作的重要性,或許一個人提出的意見,可以影響整個組織,而互相交流更可以加強這種關係。


回顧 Day24

Day24 中,談到了我第三份工作的狀態,也介紹了公司的業務。而接下來則是要介紹我在這間公司遇到的各種產品問題,以及整個背景,然後也會提及我是怎麼解決這些問題的。

公司的狀態

草創的歷史

在我和同事加入這家公司之前,它還處於起步階段。當時因預算有限,公司主要僱用了初級工程師,導致產品架構不甚完善。原有四到五個專案,經過內部評估後,三個專案被決定需要從頭開始。

產品問題點

我主要負責的是醫生端的Web介面。雖然這個專案被認為不需要重新開發,但它確實存在多個問題:

不常見的 Eslint rule:
公司有大量自定義的 Eslint 規則,多數並非業界常用。這對我來說是個挑戰,因為我已習慣了遵循 Airbnb 的 Eslint 規範。

不常見的縮排設定::
這是個很嚴重的問題,大多數的現代 JS 開發都是使用空白兩格,而這邊是使用 Eslint rule 強制使用 Tab 四格,尤其是 IDE 工具我已經是預設按下 tab 等於空白兩格,結果這個設定這造成了我經常按照原本的習慣按下 tab,然後就會整串紅。我為了解決這個問題,後來就決定把我自己用的設定檔跟公司的設定分開,這樣可以盡量避免這種錯誤。但如果今天有需求要我去開發行政管理端,那就會變成又有問題,因為行政管理端是空白兩格。

四格空行示意圖
四格空行的示意圖,這樣一個簡單的元件就會看起來非常地巢狀,當更多了就會變成一場災難。

過長的開發內容:
在這裡程式碼經常是大概三百到五百行,非常的長。不只邏輯,也把 UI 通通都放在一起,甚至一個元件的 state 可以有十幾個。這不僅使得代碼難以閱讀,也增加了耦合性。

混亂的程式碼:
這個部分其實跟上方非常有關係,因為太長了,一個檔案要塞下非常多東西,所以在查看邏輯時,一個元件內就會有相當多不同的邏輯,每次回來開發都要重新省思這邊到底有幾個邏輯,並且把他們歸類,完全不符合我 clean code 的寫法,但是原本的程式碼又非常的「clean」,其實就是沒寫註解,這導致了我閱讀困難。

邏輯高耦合性:
由於一個元件內含有過多的邏輯,這導致程式碼高度耦合。我花了不少時間在重構和解耦上。

其他:
架構面、效能面、可擴展性、UI/UX、DX(Developer Experience)等等的方面。

解決方式

漸進性重構與優化

遵循先前的策略,我持續在開發新的問題單(issue)過程中進行漸進性的重構和優化。每當需求明確後,我會同時考慮如何提升代碼品質和使專案結構更加合理。

在這個過程中,我維持了一個嚴謹的開發風格,從新增功能、代碼重構、解耦合到視覺界面調整,我進行了多方面的優化。有幸的是,這次我有資深工程師的支持,不再需要完全獨自應對所有問題。

在一次討論中,資深工程師提到了 React 的 hook 新機制的好處,這使得我們不再必需依賴像 Redux 這種主要為大型應用設計的工具。我同意這一觀點,因為簡單總是更好。因此,在後續開發中,我逐步移除了 Redux,只保留了確實必要的部分,如用戶登入狀態。

隨著時間的推進,專案的結構變得越來越清晰,而新冠疫情也讓我們的視訊看診系統受到了政府的重視,這更加速了我們的開發進度。

解決問題

在這個階段,我主要聚焦於代碼邏輯的拆分,並且是邏輯分離清晰。另外,我將用戶界面(UI)組件和邏輯組件進行了明確的分離,使得後來者在回顧代碼時,不會感到過度困擾。

我也移除了一些不太實用的 ESLint 規則。然而,由於某些規則的移除會影響到代碼的多個部分,我選擇暫時將這些問題擱置。例如,縮排問題因為範圍過大,暫時未能解決。

帶入改進與交流

像是我帶進了使用 IIFE 呼叫 API 的形式
原本大部分寫法都是:

useEffect(() => {
  const getData = async () => {
    const res = await axios.get('url');
    setData(res.data);
  };
  getData();
}, []);

我則是在之前經驗中,發現可以不用這樣寫,寫成:

useEffect(() => {
  (async () => {
    const res = await axios.get('url');
    setData(res.data);
  })();
}, []);

使用 IIFE (立即調用函數表達式) 呼叫可以更為簡潔些,畢竟這種 function 通常用一次就用不到了,就算要重用,也可以直接包成 custom hook。

後來我看我公司的同事也都跟著這麼寫,這種交流的感覺,真的很不錯。
其他還有相當多的例子,就不一一的說明了。

隨著我實現越來越多臨時性的功能要求,我也一邊實現功能,然後也做了很多重構,最後終於到了系統的極限也開始被要求的時候了。

結語

這一階段的經歷填補了我在前一家公司未完成的願望。那時,我深切地希望能改進既有的舊產品,但因轉向新的產品線而未能實現。這次的經歷確認了我具有將過時、不良系統逐步提升至可用狀態的能力。

這段經驗也讓我回想到轉職班老師經常對我們強調的開發習慣——「持續重構」。多虧了他的教誨,我學會了如何逐步改進和優化產品。

在我們的互動與討論中,我們達到了更高層次的交流,這為我們提供了更多更好的方法來逐步改善產品。

目前在醫生端(Web)的開發上,還有多個重要問題待解。下一篇文章將詳細介紹我如何全面解決這些挑戰,這當然也是基於新提出的需求來進行的工作。


文章就說到這,有什麼想法或問題,歡迎隨時找我聊聊!

這篇文章也會同步發在 medium 上,如果有興趣歡迎追蹤我。

medium: https://medium.com/@hugh-program-learning-diary-js
email: u88803494@gmail.com


上一篇
人生重構 Day24:第三份工作—穩定就是持續進步
下一篇
人生重構 Day26:深入前端—決戰產品優化升級
系列文
轉職三年 web 仔:不僅是代碼,更是人生的重構40
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
huli
iT邦新手 2 級 ‧ 2023-10-11 20:23:15

其實呼叫 API 那個我會選擇舊的寫法XD 原因之一是其實換成 IIFE 也沒有省多少程式碼,原因之二(這其實比較是重點)是可讀性,換成 IIFE 之後其實就失去了 function 名稱,而且多了一堆符號,可讀性會變差

而且如果包住的那段有錯誤發生,只看 stack trace 的話會不知道到底哪邊出錯,沒記錯的話只會顯示 anonymous

當然也可以再把 function name 加回去啦,但加回去的話其實有沒有 IIFE 都差不多了

u88803494 iT邦新手 5 級 ‧ 2023-10-11 21:07:14 檢舉

原來還有這樣的差異,我會再去注意一下這樣的問題,感謝提點~

我要留言

立即登入留言